#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SNAKE_MAX_LENGTH 20
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ' '
#define SNAKE_FOOD '$'
#define WALL_CELL '*'

//地图
char map[12][12] = {
    "************",
    "*XXXXH     *",
    "*          *",
    "*          *",
    "*          *",
    "*          *",
    "*          *",
    "*          *",
    "*          *",
    "*          *",
    "*          *",
    "************"};

//蛇的位置与长度
int snakeX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5};
int snakeY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakeLength = 5;

void addFood();                          //初始化，添加食物
void output();                           //输出模块
void gameover();                         //游戏结束的输出
void operation();                        //操作的读取和解析
int GameRun(int addX, int addY);         //游戏规则的判断
void Move(int addX, int addY, int mode); //蛇的移动控制器

//主函数
int main()
{
    addFood();
    output();
    operation();
    gameover();
}

void addFood()
{
    int x, y;
    srand(time(0)); //在随机的空白位置产生一个食物
    do
    {
        x = rand() % 21 + 1;
        y = rand() % 21 + 1;
    } while (map[y][x] != BLANK_CELL);
    map[y][x] = SNAKE_FOOD;
}

void output()
{
    printf("\n------------Gready Snake------------\n");
    for (int i = 0; i < 12; i++)
    {
        for (int j = 0; j < 12; j++)
        {
            printf("%c", map[i][j]);
        }
        printf("\n");
    }
}

void gameover()
{
    printf("Game Over!\n");
}

void operation()
{
    char c;
    char lastc = 'd';
    int addX = 0;
    int addY = 0;
    int flag;

    printf("Please input the operation(WASD/wasd): ");
    while (scanf(" %c", &c)) //不断读取指令
    {
        flag = 0;
        switch (c) //判断方向
        {
        case 'a':
        case 'A':
            if (lastc == 'd' || lastc == 'D')
            {
                flag = 1;
                break;
            }
            else
            {
                addX = -1;
                addY = 0;
                break;
            }

        case 'd':
        case 'D':
            if (lastc == 'a' || lastc == 'A')
            {
                flag = 1;
                break;
            }
            else
            {
                addX = 1;
                addY = 0;
                break;
            }

        case 'w':
        case 'W':
            if (lastc == 's' || lastc == 'S')
            {
                flag = 1;
                break;
            }
            else
            {
                addX = 0;
                addY = -1;
                break;
            }

        case 's':
        case 'S':
            if (lastc == 'w' || lastc == 'W')
            {
                flag = 1;
                break;
            }
            else
            {
                addX = 0;
                addY = 1;
                break;
            }

        default:
            flag = 2;
            break;
        }
        //异常处理，错误输入和错误移动：
        if (flag == 2)
        {
            printf("Invalid Input! Please input again(WASD/wasd): ");
            continue;
        }
        if (flag == 1)
        {
            printf("Invalid Move! Please input again(WASD/wasd): ");
            continue;
        }
        //游戏终止条件判断，1继续，0停止
        if (!GameRun(addX, addY))
        {
            break;
        }
        //继续输出
        output();
        printf("Please input the operation(WASD/wasd): ");
        //保存上次的输入操作值
        lastc = c;
    }
}

int GameRun(int addX, int addY)
{
    char next = map[snakeY[snakeLength - 1] + addY][snakeX[snakeLength - 1] + addX];
    //失败判断
    if (next == WALL_CELL || next == SNAKE_BODY)
    {
        printf("You failed! \n");
        return 0;
    }
    //吞食
    if (next == SNAKE_FOOD)
    {
        if (snakeLength >= SNAKE_MAX_LENGTH) //成功判断
        {
            printf("The snake length is over 20. You win!\n");
            return 0;
        }
        Move(addX, addY, 1); //增加长度的移动
        addFood();
    }
    else
    {
        Move(addX, addY, 0); //不增加长度的移动
    }

    return 1;
}

void Move(int addX, int addY, int mode)
{
    if (mode == 1)
    { //增加长度
        snakeLength++;
        map[snakeY[snakeLength - 2]][snakeX[snakeLength - 2]] = SNAKE_BODY; //原来的头变成身体
        snakeX[snakeLength - 1] = snakeX[snakeLength - 2] + addX;           //找头的位置
        snakeY[snakeLength - 1] = snakeY[snakeLength - 2] + addY;
        map[snakeY[snakeLength - 1]][snakeX[snakeLength - 1]] = SNAKE_HEAD;
    }
    else
    {                                                                       //不增加长度
        map[snakeY[0]][snakeX[0]] = BLANK_CELL;                             //蛇尾去除
        map[snakeY[snakeLength - 1]][snakeX[snakeLength - 1]] = SNAKE_BODY; //原来的头变成身体
        for (int i = 0; i < snakeLength - 1; i++)
        { //蛇身整体移动一格
            snakeX[i] = snakeX[i + 1];
            snakeY[i] = snakeY[i + 1];
        }
        snakeX[snakeLength - 1] += addX; //找头的位置
        snakeY[snakeLength - 1] += addY;
        map[snakeY[snakeLength - 1]][snakeX[snakeLength - 1]] = SNAKE_HEAD;
    }
}